import React, { useState, useEffect } from 'react';
import IconButton from '@material-ui/core/IconButton';
import ControlPointDuplicateOutlined from '@material-ui/icons/ControlPointDuplicateOutlined';
import Divider from '@material-ui/core/Divider';
import Checkbox from '@material-ui/core/Checkbox';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import Collapse from '@material-ui/core/Collapse';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';
import Avatar from '@material-ui/core/Avatar';
import List from '@material-ui/core/List';
import ListItemText from '@material-ui/core/ListItemText';
import { makeStyles } from '@material-ui/core/styles';
import { NavItem, g_style } from '../base/st';
import { MDel, PanelTitle, Btn, is_empty, Tip, cutTxt } from '../../nui';
import { loc } from '../../local';

const useGlobStyle = makeStyles(theme => (g_style));

const ListBox = ({ children, className, dense=false }) => <List component="nav" dense={dense} className={className}>{children}</List>;

/* left pos, text, subtext and some buttons
 *
 * hdel:    hdel(uid)
 * pos: left number
*/
const ListPos = ({ hdel, value, subvalue, pos, uid, className }) => {
    const classes = useGlobStyle();

    const Pos = () => {
        if (!pos) {
            return null;
        }

        return (
            <ListItemAvatar>
                <Avatar className={classes.blueAvatar}>{pos}</Avatar>
            </ListItemAvatar>
        );
    };

    return (
        <NavItem button className={className}>
            <Pos/>
            <ListItemText primary={value} secondary={subvalue}/>
            <ListItemSecondaryAction>
                <MDel hcmd={hdel} uid={uid}/>
            </ListItemSecondaryAction>
        </NavItem>
    );
};

const NavList = ({ hcmd, value, cur, uid, icon, cut=8 }) => {
    const getIcon = () => {
        if (icon) {
            return <ListItemIcon>{icon}</ListItemIcon>;
        }

        return null;
    };

    return (
        <NavItem button selected={cur === uid} onClick={() => hcmd(uid)}>
            {getIcon()}
            <ListItemText id={`nav.${uid}`} name={uid} primary={<div className="font-medium">{cutTxt(value, cut, cut)}</div>}/>
        </NavItem>
    );
};

const NavListSub = ({ hcmd, value, cur, uid, icon, sub, scut=9, cut=8, btsub, btpar, sel=false, sval }) => {
    const classes = useGlobStyle();
    const [open, setOpen] = useState(false);

    useEffect(() => {
        if (!sub) {
            return;
        }

        const f = sub.find(d => d.uid === cur);
        if (f) {
            setOpen(true);
        }
    }, [cur, sub])

    const getPar = () => {
        if (btpar) {
            return (
                <ListItemSecondaryAction className="mr-8">
                    {btpar()}
                </ListItemSecondaryAction>
            );
        }

        return null;
    };

    const getSub = () => {
        if (btsub) {
            return (
                <ListItemSecondaryAction>
                    {btsub()}
                </ListItemSecondaryAction>
            );
        }

        return null;
    };

    const item = () => {
        if (!sub) {
            return null;
        }

        return sub.map(d => {
            if (d.uid === "divider") {
                return <Divider key={d.value}/>
            }

            return (
                <NavItem key={d.uid} className={classes.nested} button selected={cur === d.uid} onClick={() => hcmd(d.uid)}>
                    <Tip title={d.value} pos="right-start">
                        <ListItemText name={d.uid} primary={cutTxt(d.value, scut, scut)} secondary={d.sub}/>
                    </Tip>
                    {getSub()}
                </NavItem>
            );
        });
    };

    const getIcon = () => {
        if (icon) {
            return <ListItemIcon>{icon}</ListItemIcon>;
        }

        return null;
    };

    const hclick = () => {
        if (btpar) {
            if (sel) {
                hcmd(uid);
            }
            else {
                setOpen(!open);
            }
        }
        else {
            setOpen(!open);
        }
    };

    const getItem = () => {
        if (btpar) {
            return (
                <NavItem button selected={cur === uid}>
                    {getIcon()}
                    <ListItemText name={uid} primary={<div className="font-medium">{cutTxt(value, cut, cut)}</div>} secondary={sval} onClick={hclick}/>
                    {getPar()}
                    <div onClick={() => setOpen(!open)}>
                        {open ? <ExpandLess /> : <ExpandMore />}
                    </div>
                </NavItem>
            )
        }

        return (
            <NavItem button selected={cur === uid} onClick={hclick}>
                {getIcon()}
                <ListItemText name={uid} primary={<div className="font-medium">{cutTxt(value, cut, cut)}</div>}/>
                {getPar()}
                {open ? <ExpandLess /> : <ExpandMore />}
            </NavItem>
        );
    };

    return (
        <div>
            {getItem()}
            <Collapse in={open} timeout="auto" unmountOnExit>
                <List component="div" disablePadding>
                    {item()}
                </List>
            </Collapse>
        </div>
    );
};

const ListCheck = ({ checked, setChecked, uid, value, subvalue, className }) => {
    const hcmd = (v) => () => {
        const cur = checked.indexOf(v);
        const tmp = [...checked];

        if (cur === -1) {
            tmp.push(v);
        } else {
            tmp.splice(cur, 1);
        }

        setChecked(tmp);
    };

    return (
        <NavItem button className={className} onClick={hcmd(uid)}>
            <ListItemIcon>
                <Checkbox id={"ck" + uid} checked={checked.indexOf(uid) !== -1} color="primary"/>
            </ListItemIcon>
            <ListItemText primary={value} secondary={subvalue}/>
        </NavItem>
    );
};

/* data = [
 *     {uid: "xx", sn: "xx"}
 * ]
*/
const TList = ({ lst, cur, setCur, high=400 }) => {
    const [checked, setChecked] = useState([]);

    const hdel = (v) => {
        const tmp = cur.filter(d => d.uid !== v);
        setCur(tmp);
    };

    const getHead = () => {
        if (is_empty(cur)) {
            return null;
        }

        return cur.map(d => <ListPos key={d.uid} value={d.sn} uid={d.uid} hdel={hdel}/>);
    };

    const getItem = () => {
        if (is_empty(lst)) {
            return null;
        }

        const ret = [];

        const set = new Set();
        if (!is_empty(cur)) {
            cur.forEach(d => set.add(d.uid));
        }

        lst.forEach(d => {
            if (set.has(d.uid)) {
                return;
            }

            ret.push(<ListCheck key={d.uid} value={d.sn} checked={checked} setChecked={setChecked} uid={d.uid}/>);
        });

        return ret;
    };

    const addHead = () => {
        if (is_empty(checked)) {
            return;
        }

        const set = new Set();

        checked.forEach(d => set.add(d));

        if (!is_empty(cur)) {
            cur.forEach(d => set.add(d.uid));
        }

        const ret = [];

        lst.forEach(d => {
            if (set.has(d.uid)) {
                ret.push(d);
            }
        });

        setChecked([]);
        setCur(ret);
    };

    const getNum = () => {
        if (is_empty(cur)) {
            return 0;
        }

        return cur.length;
    };

    const selectAll = () => {
        if (is_empty(lst)) {
            return;
        }

        const set = new Set();
        if (!is_empty(cur)) {
            cur.forEach(d => set.add(d.uid));
        }

        const ret = [];

        lst.forEach(d => {
            if (set.has(d.uid)) {
                return;
            }

            ret.push(d.uid);
        });

        setChecked(ret);
    };

    const rmAll = () => {
        if (!window.confirm(loc("qdsc"))) {
            return;
        }

        setCur(null);
    };

    const Left = () => (
        <div className="inline-flex">
            <Btn name="addhead" hcmd={addHead}>{"<<"}</Btn>
            <Btn className="ml-4" hcmd={selectAll}>{loc("qs")}</Btn>
        </div>
    );

    return (
        <div className="flex flex-row">
            <div className="w-1/2 border-r-2 border-blue-300 overflow-y-auto" style={{ height: high + "px" }}>
                <PanelTitle cl="green" left={`${loc("zs")}: ${getNum()}`} right={<Btn hcmd={rmAll}>{loc("qbsc")}</Btn>}/>
                <div className="overflow-y-auto" style={{ height: high - 60 + "px" }}>
                    <ListBox>
                        {getHead()}
                    </ListBox>
                </div>
            </div>
            <div className="w-1/2 flex flex-col">
                <PanelTitle cl="green" left={<Left/>}/>
                <div className="overflow-y-auto" style={{ height: high - 60 + "px" }}>
                    <ListBox>
                        {getItem()}
                    </ListBox>
                </div>
            </div>
        </div>
    );
};

/* text and subtext list item with left move button
 *
 * pos: left number
 * click: hcmd(uid)
*/
const ListMove = ({ pos, hcmd, value, subvalue, uid, className }) => {
    const classes = useGlobStyle();

    const Pos = () => {
        if (!pos) {
            return null;
        }

        return (
            <ListItemAvatar>
                <Avatar className={classes.grayAvatar}>{pos}</Avatar>
            </ListItemAvatar>
        );
    };

    return (
        <NavItem button className={className}>
            <ListItemIcon>
                <IconButton id={"lm" + uid} edge="end" onClick={() => hcmd(uid)}>
                    <ControlPointDuplicateOutlined style={{ color: "#4299E1" }}/>
                </IconButton>
            </ListItemIcon>
            <Pos/>
            <ListItemText primary={value} secondary={subvalue}/>
        </NavItem>
    );
};

export {ListMove, TList, ListCheck, NavListSub, NavList, ListPos, ListBox};
